package compiler.mine;

import compiler.*;

/**
 * Created by Administrator on 2017/2/2.
 */
public class Sc extends NfaConstructor {
    private NfaManager manager;
    private Lexer lexer;

    public Sc(Lexer lexer) throws Exception {
        super(lexer);
        this.manager = new NfaManager();
        this.lexer = lexer;
    }

    public void factor(NfaPair pairOut) throws Exception {
        boolean handled = false;
        handled = constructStarClosure(pairOut);
        if (handled == false) {
            handled = constructPlusClosure(pairOut);
        }

        if (handled == false) {
            handled = constructOptionsClosure(pairOut);
        }

    }

    public boolean constructStarClosure(NfaPair pairOut) throws Exception {
        /*
         * term*
    	 */
        Nfa start, end;
        term(pairOut);

        if (lexer.match(Lexer.Token.ASTERISK) == false) {
            return false;
        }

        start = manager.newNfa();
        end = manager.newNfa();

        start.next = pairOut.startNode;
        pairOut.endNode.next = pairOut.startNode;

        start.next2 = end;
        pairOut.endNode.next2 = end;

        pairOut.startNode = start;
        pairOut.endNode = end;

        lexer.advance();

        return true;
    }

    public boolean constructPlusClosure(NfaPair pairOut) throws Exception {
    	/*
    	 * term+
    	 */
        Nfa start, end;
        term(pairOut);

        if (lexer.match(Lexer.Token.PLUS) == false) {
            return false;
        }

        start = manager.newNfa();
        end = manager.newNfa();

        start.next = pairOut.startNode;
        pairOut.endNode.next2 = end;
        pairOut.endNode.next = pairOut.startNode;


        pairOut.startNode = start;
        pairOut.endNode = end;

        lexer.advance();
        return true;
    }

    public boolean constructOptionsClosure(NfaPair pairOut) throws Exception {
    	/*
    	 * term?
    	 */
        Nfa start, end;
        term(pairOut);

        if (lexer.match(Lexer.Token.QUESTION_MARK) == false) {
            return false;
        }

        start = manager.newNfa();
        end = manager.newNfa();

        start.next = pairOut.startNode;
        pairOut.endNode.next = end;

        start.next2 = end;

        pairOut.startNode = start;
        pairOut.endNode = end;

        lexer.advance();

        return true;
    }

    public void term(NfaPair pairOut) throws Exception {
        /*
         * term ->  character | [...] | [^...] | [character-charcter] | . | (expr)
         *
         */


        constructNfaForSingleCharacter(pairOut);
    }

    public boolean constructNfaForSingleCharacter(NfaPair pairOut) throws Exception {
        if (lexer.match(Lexer.Token.L) == false) {
            return false;
        }

        Nfa start = null;
        start = pairOut.startNode = manager.newNfa();
        pairOut.endNode = pairOut.startNode.next = manager.newNfa();

        start.setEdge(lexer.getCurrentChar());

        lexer.advance();

        return true;
    }
}
